#ifndef MENU_H
#define MENU_H
/****************/
/****无需修改******/
/****************/
#include "stdlib.h"
#include "stdarg.h"
#include "string.h"
#include "stdint.h"

// 宏封装，隐藏 NULL 结尾
#define CREATE_CONTAINER_NODE(desc, parent, ...) \
    createContainerNode(desc, parent, __VA_ARGS__, NULL)
#define CREATE_FUNCTION_NODE(desc, func, parent, ...) \
    createFunctionNode(desc, func, parent, ##__VA_ARGS__, NULL)

/**
 * @brief 页面数据记录与选择结构体（页面结构体）
 */
typedef struct rangeBlock{
    int upper;         // 上界
    int lower;         // 下界
    int upperValue;    // 当前上界值
    int lowerValue;    // 当前下界值
    int value;         // 当前值
}rangeBlock;

/**
 * @brief 功能节点元结构体
 * @details 所谓菜单就是由该节点组成的树，节点树包含了菜单的所有信息
 */
typedef struct MenuNode MenuNode;
struct MenuNode {
    char *description;              // 名称
    char *oder;                     // 可选指令
    MenuNode **subItems;            // 子节点元指针的指针
    void (*action)(void);           // 功能函数指针
    int isFunction;                 // 标志位，1 表示功能元，0 表示元夹
    MenuNode *parent;               // 指向父节点元的指针
};

/**
 * @brief 菜单功能最终执行器
 * @details 能存储当前菜单选中的位号
 */
typedef struct MenuControler{
    MenuNode *currentMenu;           // 当前菜单元
    rangeBlock selectedIdx;            // 选中的当前菜单元的子菜单元位号（有界数字）
    int totalItems;                  // 子菜单元的总个数
}MenuControler;
void block_test_func();
extern MenuControler globalMenuControler;
void rangeBlock_init(rangeBlock *rb, int lower, int upper, int lowerValue, int upperValue, int initValue);
void rangeBlock_increment(rangeBlock *rb);
void rangeBlock_decrement(rangeBlock *rb);
MenuNode *createContainerNode(const char *desc, MenuNode *parent, ...);
MenuNode *createFunctionNode(const char *desc, void (*func)(void), MenuNode *parent, ...);
void freeMenuNode(MenuNode *node);
int countSubItems(MenuNode *node);
void initMenuControler(MenuControler *controller, MenuNode *rootMenu);
void decrementSelection(MenuControler *controller);
void incrementSelection(MenuControler *controller);
void exitMenu(MenuControler *controller);
void useSelected(MenuControler *controller);
void MenuOLED_PrintString_N(uint8_t x, uint8_t y, char *str);
void MenuOLED_PrintString_R(uint8_t x, uint8_t y, char *str);
void menuOLED_LineX_N(MenuNode * MenuNode, int line);
void menuOLED_LineX_R(MenuNode * MenuNode, int line);
void menuOLED_MenuControl_Print(MenuControler * Controler);
void Menu_Init();
#endif
